//! Built-in commands for R-XShell
//!
//! This module contains implementations of common shell commands
//! that are built into R-XShell for cross-platform compatibility.

pub mod ls;

use crate::error::Result;
use crate::shell::Shell;
use async_trait::async_trait;

/// Trait for built-in commands
#[async_trait]
pub trait BuiltinCommand {
    /// Execute the command with given arguments
    async fn execute(&self, shell: &Shell, args: Vec<String>) -> Result<String>;
    
    /// Get command name
    fn name(&self) -> &'static str;
    
    /// Get command description
    fn description(&self) -> &'static str;
    
    /// Get command usage
    fn usage(&self) -> &'static str;
}

/// Registry for built-in commands
pub struct CommandRegistry {
    commands: std::collections::HashMap<String, Box<dyn BuiltinCommand + Send + Sync>>,
}

impl std::fmt::Debug for CommandRegistry {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        f.debug_struct("CommandRegistry")
            .field("commands", &format!("{} commands", self.commands.len()))
            .finish()
    }
}

impl CommandRegistry {
    /// Create a new command registry with default commands
    pub fn new() -> Self {
        let mut registry = Self {
            commands: std::collections::HashMap::new(),
        };
        
        // Register built-in commands
        registry.register(Box::new(ls::LsCommand::new()));
        
        registry
    }
    
    /// Register a new command
    pub fn register(&mut self, command: Box<dyn BuiltinCommand + Send + Sync>) {
        self.commands.insert(command.name().to_string(), command);
    }
    
    /// Get a command by name
    pub fn get(&self, name: &str) -> Option<&(dyn BuiltinCommand + Send + Sync)> {
        self.commands.get(name).map(|cmd| cmd.as_ref())
    }
    
    /// List all available commands
    pub fn list_commands(&self) -> Vec<&str> {
        self.commands.keys().map(|s| s.as_str()).collect()
    }
    
    /// Execute a built-in command if it exists
    pub async fn execute(&self, shell: &Shell, command: &str, args: Vec<String>) -> Option<Result<String>> {
        if let Some(cmd) = self.get(command) {
            Some(cmd.execute(shell, args).await)
        } else {
            None
        }
    }
}

impl Default for CommandRegistry {
    fn default() -> Self {
        Self::new()
    }
}